package cn.k7g.alloy.autoconfiguration;

import cn.k7g.alloy.ioc.processor.EnhanceObjectMapperProcess;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.util.ArrayList;
import java.util.List;

/**
 * import 入口
 * @author victor-wu
 * @date 2024年4月3日
 */
@Slf4j
public class AlloyAutoConfigurationSelector implements ImportSelector, BeanFactoryAware {

    public static final String ENABLE_ENHANCE_EXCEPTION_RESPONSE = "cn.k7g.alloy.autoconfiguration.EnableOptions.EnhanceExceptionMessage";

    protected Class<?> getAnnotationClass() {
        return EnableAlloyAutoConfiguration.class;
    }

    private BeanFactory beanFactory;
    private BeanDefinitionRegistry registry;

    private ConfigurableBeanFactory configurableBeanFactory;

    static AnnotationAttributes enableAlloy;

    @Override
    public String[] selectImports(AnnotationMetadata importMetadata) {
        enableAlloy = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(getAnnotationClass().getName(), false));
        if (enableAlloy.getBoolean("enableEnhanceExceptionMessage")) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(EnableOptions.EnhanceExceptionMessage.class);
            registry.registerBeanDefinition(EnableOptions.EnhanceExceptionMessage.class.getSimpleName(), builder.getBeanDefinition());
        }

        if (enableAlloy.getBoolean("enableIgnoreInvoke")) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(EnableOptions.EnableIgnoreInvoke.class);
            registry.registerBeanDefinition(EnableOptions.EnableIgnoreInvoke.class.getSimpleName(), builder.getBeanDefinition());
        }

        if (enableAlloy.getBoolean("enableEnhanceObjectMapper") && this.configurableBeanFactory != null) {
            this.configurableBeanFactory.addBeanPostProcessor(new EnhanceObjectMapperProcess(enableAlloy.getBoolean("enableEnhanceObjectMapper"), beanFactory));
        }

        List<String> ret = new ArrayList<>();
        ret.add(AlloyAutoConfigurationInit.class.getName());
        ret.add(AlloyBeanDefinitionRegister.class.getName());
        return ret.toArray(new String[]{});
    }


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        /*
         在SPRING源码中 selector 阶段， beanFactory 一定是 BeanDefinitionRegistry，且没有/无法继承实现
         参考 ConfigurationClassParser
         */
        this.registry = (BeanDefinitionRegistry) beanFactory;

        if (beanFactory instanceof ConfigurableBeanFactory) {
            this.configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
        }
    }

}
